﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DistinctPhoto
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btInputFloder_Click(object sender, EventArgs e)
        {
            if (DialogResult.OK == folderBrowserDialog1.ShowDialog())
            {
                tbInputFloder.Text = folderBrowserDialog1.SelectedPath;
            }
        }

        private void btOutputFloder_Click(object sender, EventArgs e)
        {
            if (DialogResult.OK == folderBrowserDialog1.ShowDialog())
            {
                tbOutputFolder.Text = folderBrowserDialog1.SelectedPath;
            }
        }

        private void btDeal_Click(object sender, EventArgs e)
        {
            string sourcepath = tbInputFloder.Text;
            string targetpath = tbOutputFolder.Text;
            DealPhoto(sourcepath, targetpath);
            MessageBox.Show("OK");
        }
        private void DealPhoto(string sourcpath, string targetpath)
        {
            Dictionary<string, string> file_md5 = new Dictionary<string, string>();
            DirectoryInfo di = new DirectoryInfo(sourcpath);
            get_filesmd5_in_dir(file_md5, di);
            List<string> md5s = new List<string>();
            DirectoryInfo tdir = new DirectoryInfo(targetpath);

            if (tdir.GetDirectories("dup").Count() == 0)
            {
                tdir.CreateSubdirectory("dup");
            }
            DirectoryInfo dupdir = tdir.GetDirectories("dup").First();
            long idx = 0;
            foreach (string k in file_md5.Keys)
            {
                string md5 = file_md5[k];
                FileInfo fi = new FileInfo(k);
                if (md5s.Contains(md5))
                {
                    //移到重复文件夹，重命名。序号+原名。
                    string filename = string.Format("{0}_{1}", idx++, fi.Name);
                    File.Move(k, dupdir.FullName + "\\" + filename);
                }
                else
                {
                    //移到目标文件夹，重命名为修改时间+md5。
                    DateTime last_write_time = fi.LastWriteTime;
                    string newfilename = string.Format("{0}_{1}{2}", last_write_time.ToString("yyyyMMddHHmmss"), md5, fi.Extension);
                    File.Move(fi.FullName, tdir.FullName + "\\" + newfilename);
                    md5s.Add(md5);
                }
            }
        }
        private void get_filesmd5_in_dir(Dictionary<string, string> md5s, DirectoryInfo sourcepath)
        {
            //取路径下的子目录下的文件
            foreach (DirectoryInfo subdir in sourcepath.GetDirectories())
            {
                get_filesmd5_in_dir(md5s, subdir);
            }
            //取本目录下的文件
            foreach (FileInfo fi in sourcepath.GetFiles("*.jpg"))
            {
                md5s.Add(fi.FullName, GetMD5HashFromFile(fi.FullName));
            }
        }

        /// <summary>  
        /// 获取文件的MD5码  
        /// </summary>  
        /// <param name="fileName">传入的文件名（含路径及后缀名）</param>  
        /// <returns></returns>  
        public string GetMD5HashFromFile(string fileName)
        {
            try
            {
                FileStream file = new FileStream(fileName, System.IO.FileMode.Open);
                MD5 md5 = new MD5CryptoServiceProvider();
                byte[] retVal = md5.ComputeHash(file);
                file.Close();
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < retVal.Length; i++)
                {
                    sb.Append(retVal[i].ToString("x2"));
                }
                return sb.ToString();
            }
            catch (Exception ex)
            {
                throw new Exception("GetMD5HashFromFile() fail,error:" + ex.Message);
            }
        }
    }
}
